using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Xna.Framework;

using GarageGames.Torque.Core;
using GarageGames.Torque.Util;
using GarageGames.Torque.Sim;
using GarageGames.Torque.T3D;
using GarageGames.Torque.SceneGraph;
using GarageGames.Torque.MathUtil;
using GarageGames.Torque.T3D.RigidCollision;
using GarageGames.Torque.Materials;

namespace TimeWar
{
    [TorqueXmlSchemaType]
    public class WeaponComponent3D : TorqueComponent
    {
        //======================================================
        #region Static methods, fields, constructors
        public static void ProcessProjectileCollision(T3DRigidComponent us, T3DRigidComponent them, RigidContactConstraint.Contact[] contacts, int contactCount, float dt)
        {
            //produce an impact effect
            T3DSceneComponent enemySceneComponent = them.Owner.Components.FindComponent<T3DSceneComponent>();
            Vector3 enemyPosition = enemySceneComponent.Position;
            Explosion(enemyPosition);

            //get the enemy object type
            TorqueObjectType typeEnemy = TorqueObjectDatabase.Instance.GetObjectType("Enemy");

            if (them.Owner.TestObjectType(typeEnemy))
            {
                //remove the enemy shape
                them.Owner.MarkForDelete = true;
            }
        }

        public static void Explosion(Vector3 position)
        {
            ParticleEffects.Explosion(position);
        }
        #endregion

        //======================================================
        #region Constructors
        public WeaponComponent3D()
        {

        }
        #endregion

        //======================================================
        #region Public properties, operators, constants, and enums
        public ProjectileTemplate ProjectileTemplate
        {
            set { _projectileTemplate = value; }
            get { return _projectileTemplate; }
        }
        #endregion

        //======================================================
        #region Public methods

        public virtual void ProcessTick(Move move, float dt)
        {
            // todo: perform processing for component here
        }

        public virtual void InterpolateTick(float k)
        {
            // todo: interpolate between ticks as needed here
        }

        public override void CopyTo(TorqueComponent obj)
        {
            base.CopyTo(obj);
            WeaponComponent3D obj2 = (WeaponComponent3D)obj;
            obj2.ProjectileTemplate = obj2.ProjectileTemplate;
        }

        public void FireWeapon(float projectileSpeed)
        {

            //spawn the projectile
            ProjectileTemplate objProjectile = (ProjectileTemplate)_projectileTemplate.Clone();

            //set the initial position of the projectile
            Vector3 vPosition = Owner.Components.FindComponent<T3DSceneComponent>().Position;
            vPosition = Vector3.Add(vPosition, new Vector3(0, 0, 2));
            objProjectile.Components.FindComponent<T3DSceneComponent>().Position = vPosition;

            //set the projectile's forward velocity
            T3DRigidComponent rigidComponent = objProjectile.Components.FindComponent<T3DRigidComponent>();
            Matrix playerTranslationMatrix = Owner.Components.FindComponent<T3DSceneComponent>().Transform;
            Vector3 forward = MatrixUtil.MatrixGetRow(1, ref playerTranslationMatrix);
            Vector3 vel = (forward * projectileSpeed);
            rigidComponent.Velocity += vel;

            //register the projectile with the object database
            TorqueObjectDatabase.Instance.Register(objProjectile);
        }



        #endregion

        //======================================================
        #region Private, protected, internal methods

        protected override bool _OnRegister(TorqueObject owner)
        {
            if (!base._OnRegister(owner))
                return false;

            // todo: perform initialization for the component

            // todo: look up interfaces exposed by other components
            // E.g., 
            // _theirInterface = Owner.Components.GetInterface<ValueInterface<float>>("float", "their interface name");
            //give the player some physics attributes, like gravity and collision
            _projectileTemplate = new ProjectileTemplate();
            _projectileTemplate.Timer = .5f;
            T3DRigidComponent projectilePhysics = _projectileTemplate.Components.FindComponent<T3DRigidComponent>();
            projectilePhysics.OnCollision = ProcessProjectileCollision;

            ProcessList.Instance.AddTickCallback(Owner, _projectileTemplate);

            //add a new template to the TorqueObjectDatabase dictionary
            TorqueObjectDatabase.Instance.Dictionary.SetValue<TorqueObject>(_projectileTemplate, _projectileTemplate.Name, null);

            return true;
        }

        protected override void _OnUnregister()
        {
            // todo: perform de-initialization for the component

            base._OnUnregister();
        }

        protected override void _RegisterInterfaces(TorqueObject owner)
        {
            base._RegisterInterfaces(owner);

            // todo: register interfaces to be accessed by other components
            // E.g.,
            // Owner.RegisterCachedInterface("float", "interface name", this, _ourInterface);
        }


        #endregion

        //======================================================
        #region Private, protected, internal fields
        private ProjectileTemplate _projectileTemplate;
        #endregion
    }
}
